#include <unistd.h>
#include <iostream>
#include <cstdlib>  //等价于#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdio>
#include <string>
#include <cstring>

using namespace std;

//parent process
void Reader(int Rfd) 
{
    char buffer[1024] = {0};
    while (true)
    {
        buffer[0] = '\0';   //清空缓冲区,告诉读者，这是一个字符串   

        //从文件中读取字符串
        ssize_t n = read(Rfd, buffer, sizeof(buffer));   //sizeof(buffer) != strlen(buffer)
        if (n > 0)   //n是读取的字节数
        {
            buffer[n] = 0;   //字符串末尾加上'\0'
            cout << "Received message: " << buffer << endl;
        }
    }
    
}

//child process
void Writer(int Wfd) 
{   
    string str = "Hello, im child process!";
    pid_t pid = getpid();
    int number = 0;

    char buffer[1024] = {0};

    while (true)
    {
        //构建发送字符串
        buffer[0] = '\0';   //清空缓冲区,告诉读者，这是一个字符串
        snprintf(buffer, sizeof(buffer), "%s pid = %d, number = %d\n", str.c_str(), pid, number++);
        // cout << buffer << endl;
        sleep(10);

        //发送字符串给父进程（只要你是一个文件，存在fd,就可以用write向文件写入内容）
        write(Wfd, buffer, strlen(buffer));     //write是写入到了文件缓冲区

    }
    

}


int main() 
{
    int pipefd[2] = {0};
    int ret = pipe(pipefd);     //创建内存管道文件，0是read端，1是write端。虽然fd不同，但是是同一个文件。
    if (ret < 0) 
    {
        cout << "Failed to create pipe" << endl;
        return -1;
    }

    // cout << "pipefd[0] = " << pipefd[0] << ", pipefd[1] = " << pipefd[1] << endl;

    pid_t id = fork();
    
    if (id < 0) 
    {
        cout << "Failed to fork" << endl;
        return -1;
    }

    //子进程写，父进程读
    if (id == 0)
    {
        // child process
        close(pipefd[0]);
        //ipc code 
        Writer(pipefd[1]);      //不断写

        close(pipefd[1]);
        exit(0);
    }

    // parent process
    close(pipefd[1]);
    //ipc code 

     //虽然子进程将pipepid[0]关闭了，但是只会让file结构--，父进程还是可以对pipefd[0]进行读操作的。
    Reader(pipefd[0]);      //不断读(时间片导致并不会某个进程死循环)

    pid_t retid = waitpid(id, nullptr, 0);
    if (retid < 0)  
    {
        cout << "Failed to wait child process" << endl; 
        return 3;
    }
    close(pipefd[0]);

    return 0;
}    